﻿using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace AiFrame.InterfaceLib.Data.Patterns
{
    /// <summary>
    /// A basic observable list.
    /// </summary>
    /// <typeparam name="T">The type of the data object.</typeparam>
    public abstract class BaseObservableList<T>: List<T>, INotifyCollectionChanged
    {
        /// <summary>
        /// The update count.
        /// </summary>
        private int updateCount = 0;

        /// <summary>
        /// Begins an update.
        /// </summary>
        public void BeginUpdate()
        {
            updateCount += 1;
        }

        /// <summary>
        /// Ends an update.
        /// </summary>
        public void EndUpdate()
        {
            updateCount -= 1;
            this.OnItemsReset();
        }

        /// <summary>
        /// Fills the list with new items after the old ones
        /// have been deleted from the list.
        /// </summary>
        /// <param name="list">The new list.</param>
        public void Fill(IObservableList<T> list)
        {
            base.Clear();
            foreach (T item in list)
            {
                base.Add(item);
            }
            this.OnItemsAdded(this);
        }

        /// <summary>
        /// Method for the item replace event.
        /// </summary>
        /// <param name="item">The replaced item.</param>
        protected void OnItemReplace(T item)
        {
            if ((this.CollectionChanged != null) && (updateCount == 0))
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                     NotifyCollectionChangedAction.Replace, item));
            }
        }

        /// <summary>
        /// Method for the items reset event.
        /// </summary>
        protected void OnItemsReset()
        {
            if ((this.CollectionChanged != null) && (updateCount == 0))
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                     NotifyCollectionChangedAction.Reset));
            }
        }

        /// <summary>
        /// Method for the item removed event.
        /// </summary>
        /// <param name="item">The removed item.</param>
        /// <param name="index">The index of the removed item.</param>
        protected void OnItemRemoved(T item, int index)
        {
            if ((this.CollectionChanged != null) && (updateCount == 0))
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                     NotifyCollectionChangedAction.Remove, item, index));
            }
        }

        /// <summary>
        /// Method for the item added event.
        /// </summary>
        /// <param name="item">The added item.</param>
        protected void OnItemAdded(T item)
        {
            if ((this.CollectionChanged != null) && (updateCount == 0))
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                     NotifyCollectionChangedAction.Add, item));
            }
        }

        /// <summary>
        /// Method for the items added event.
        /// </summary>
        /// <param name="items">The added items.</param>
        protected void OnItemsAdded(IList items)
        {
            if ((this.CollectionChanged != null) && (updateCount == 0))
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(

                     NotifyCollectionChangedAction.Add, items, 0));

            }
        }

        /// <summary>
        /// A public method to invoke the items reset event.
        /// </summary>
        public void InvokeNotificationEvent()
        {
            OnItemsReset();
        }

        #region Implementation of INotifyCollectionChanged

        /// <summary>
        /// The collection changed event handler.
        /// </summary>
        public event NotifyCollectionChangedEventHandler CollectionChanged;


        #endregion
    }
}
